#include "TcpServer.h"
#include <QCryptographicHash>
#include <QDateTime>
#include <QFileInfo>
#include <QJsonDocument>
#include <QJsonObject>
#include <QFile>
#include <QDebug>

DatabaseAccess::DatabaseAccess(QObject *parent) : QObject(parent) {
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName("mydatabase_image.db");  // 使用不同的数据库文件名
    if (!db.open()) {
        qDebug() << "Failed to open database";
    } else {
        qDebug() << "Database opened successfully";
    }
    initializeImageStorage();
}

void DatabaseAccess::initializeImageStorage() {
    m_imageStoragePath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/images/";
    QDir dir;
    if (!dir.exists(m_imageStoragePath)) {
        if (dir.mkpath(m_imageStoragePath)) {
            qDebug() << "Created image storage directory:" << m_imageStoragePath;
        } else {
            qDebug() << "Failed to create image storage directory:" << m_imageStoragePath;
        }
    } else {
        qDebug() << "Image storage directory exists:" << m_imageStoragePath;
    }
}

QString DatabaseAccess::saveImageMessage(int patientId, int doctorId, const QString &direction, 
                                        const QByteArray &imageData, const QString &fileName) {
    // 生成唯一文件名
    QString timestamp = QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss");
    QString hash = QCryptographicHash::hash(imageData, QCryptographicHash::Md5).toHex().left(8);
    QFileInfo fileInfo(fileName);
    QString uniqueFileName = QString("%1_%2_%3.%4")
        .arg(timestamp)
        .arg(hash)
        .arg(patientId)
        .arg(fileInfo.suffix().isEmpty() ? "jpg" : fileInfo.suffix());
    
    QString filePath = m_imageStoragePath + uniqueFileName;
    
    // 保存文件到磁盘
    QFile file(filePath);
    if (!file.open(QIODevice::WriteOnly)) {
        qDebug() << "Failed to save image file:" << filePath;
        return QString();
    }
    file.write(imageData);
    file.close();
    
    qDebug() << "Image saved to:" << filePath << "Size:" << imageData.size();
    
    // 保存记录到数据库
    QSqlQuery query;
    query.prepare("INSERT INTO Chats (patient_id, doctor_id, direction, date, content, message_type, file_name, file_size) "
                  "VALUES (?, ?, ?, ?, ?, 'image', ?, ?)");
    query.addBindValue(patientId);
    query.addBindValue(doctorId);
    query.addBindValue(direction);
    query.addBindValue(QDateTime::currentDateTime());
    query.addBindValue("[图片]");  // 显示文本
    query.addBindValue(uniqueFileName);
    query.addBindValue(imageData.size());
    
    if (!query.exec()) {
        qDebug() << "Failed to insert image record:" << query.lastError().text();
        // 删除已保存的文件
        QFile::remove(filePath);
        return QString();
    }
    
    qDebug() << "Image record saved to database, unique filename:" << uniqueFileName;
    return uniqueFileName;
}

bool DatabaseAccess::executeQuery(const QString &queryStr) {
    QSqlQuery query;
    if (!query.exec(queryStr)) {
        qDebug() << "Query failed: " << query.lastError().text();
        return false;
    }
    return true;
}

QSqlQuery DatabaseAccess::runQuery(const QString &queryStr) {
    QSqlQuery query;
    if (!query.exec(queryStr)) {
        qDebug() << "Query failed: " << query.lastError().text();
    }
    return query;
}

ClientConnection::ClientConnection(QTcpSocket *socket, Server *server, QObject *parent)
    : QObject(parent), clientSocket(socket), m_server(server), 
      m_expectedSize(0), m_currentMessageType(SQL_QUERY), m_headerReceived(false) {
    connect(clientSocket, &QTcpSocket::readyRead, this, &ClientConnection::slotReadyRead);
    connect(clientSocket, &QTcpSocket::disconnected, this, &ClientConnection::slotDisconnected);
}

void ClientConnection::slotReadyRead() {
    m_buffer.append(clientSocket->readAll());

    while (!m_buffer.isEmpty()) {
        if (!m_headerReceived) {
            // ----- JSON（图片上传，形如 {"..."}）-----
            if (m_buffer.startsWith("{\"")) {
                // 原逻辑：查找 JSON 结束符 '}\n'
                int jsonEnd = m_buffer.indexOf("}\n");
                if (jsonEnd == -1) {
                    return; // 等待更多数据
                }
                QByteArray jsonData = m_buffer.left(jsonEnd + 1);
                m_buffer.remove(0, jsonEnd + 2); // 去掉 '}\n'
                handleJsonMessage(jsonData);
                continue;
            }

            // ----- 二进制头（8 字节：msgType + expectedSize）-----
            if (m_buffer.size() >= 8) {
                QDataStream stream(m_buffer);
                stream.setByteOrder(QDataStream::LittleEndian);

                quint32 msgType;
                stream >> msgType >> m_expectedSize;

                if (msgType <= IMAGE_DOWNLOAD) {
                    m_currentMessageType = static_cast<MessageType>(msgType);
                    m_headerReceived = true;
                    m_buffer.remove(0, 8);
                } else {
                    // ----- 普通 SQL 文本（无有效二进制头）-----
                    // 改动点：优先用 ';' 作为结束符，其次兼容 '\n'
                    int semiPos = m_buffer.indexOf(';');
                    if (semiPos != -1) {
                        QByteArray queryData = m_buffer.left(semiPos + 1); // 含分号
                        m_buffer.remove(0, semiPos + 1);
                        QString query = QString::fromUtf8(queryData).trimmed();
                        if (!query.isEmpty()) handleSqlQuery(query);
                        continue;
                    }
                    int newlinePos = m_buffer.indexOf('\n');
                    if (newlinePos != -1) {
                        QByteArray queryData = m_buffer.left(newlinePos);
                        m_buffer.remove(0, newlinePos + 1);
                        QString query = QString::fromUtf8(queryData).trimmed();
                        if (!query.isEmpty()) handleSqlQuery(query);
                        continue;
                    }
                    return; // 等待更多数据
                }
            } else {
                // ----- 普通 SQL 文本（缓冲不足 8 字节，直接按文本处理）-----
                // 改动点：优先 ';'，其次 '\n'
                int semiPos = m_buffer.indexOf(';');
                if (semiPos != -1) {
                    QByteArray queryData = m_buffer.left(semiPos + 1);
                    m_buffer.remove(0, semiPos + 1);
                    QString query = QString::fromUtf8(queryData).trimmed();
                    if (!query.isEmpty()) handleSqlQuery(query);
                    continue;
                }
                int newlinePos = m_buffer.indexOf('\n');
                if (newlinePos != -1) {
                    QByteArray queryData = m_buffer.left(newlinePos);
                    m_buffer.remove(0, newlinePos + 1);
                    QString query = QString::fromUtf8(queryData).trimmed();
                    if (!query.isEmpty()) handleSqlQuery(query);
                    continue;
                }
                return; // 暂无完整一条
            }
        }

        // ----- 已收到有效的二进制头，按定长读取消息体 -----
        if (m_headerReceived) {
            if (m_buffer.size() < m_expectedSize) {
                return; // 等待更多数据
            }

            QByteArray messageData = m_buffer.left(m_expectedSize);
            m_buffer.remove(0, m_expectedSize);

            switch (m_currentMessageType) {
                case SQL_QUERY: {
                    QString query = QString::fromUtf8(messageData).trimmed();
                    if (!query.isEmpty()) handleSqlQuery(query);
                    break;
                }
                case IMAGE_UPLOAD: {
                    handleImageUpload(messageData);
                    break;
                }
                case IMAGE_DOWNLOAD: {
                    QString fileName = QString::fromUtf8(messageData).trimmed();
                    handleImageDownload(fileName);
                    break;
                }
            }

            // 重置状态
            m_headerReceived = false;
            m_expectedSize = 0;
        }
    }
}


void ClientConnection::handleJsonMessage(const QByteArray &jsonData) {
    QJsonParseError error;
    QJsonDocument doc = QJsonDocument::fromJson(jsonData, &error);
    
    if (error.error != QJsonParseError::NoError) {
        qDebug() << "JSON parse error:" << error.errorString();
        clientSocket->write("failed:invalid_json");
        clientSocket->flush();
        return;
    }
    
    QJsonObject obj = doc.object();
    
    // 检查是否是图片上传消息
    if (obj.contains("image_data")) {
        int patientId = obj["patient_id"].toInt();
        int doctorId = obj["doctor_id"].toInt();
        QString direction = obj["direction"].toString();
        QString fileName = obj["filename"].toString();
        QString base64Data = obj["image_data"].toString();
        
        // 解码Base64数据
        QByteArray imageData = QByteArray::fromBase64(base64Data.toUtf8());
        
        if (imageData.isEmpty()) {
            clientSocket->write("failed:invalid_image_data");
            clientSocket->flush();
            return;
        }
        
        // 保存图片
        DatabaseAccess dbAccess;
        QString savedFileName = dbAccess.saveImageMessage(patientId, doctorId, direction, imageData, fileName);
        
        if (!savedFileName.isEmpty()) {
            clientSocket->write("success:" + savedFileName.toUtf8());
        } else {
            clientSocket->write("failed:save_error");
        }
        clientSocket->flush();
    } else {
        clientSocket->write("failed:unknown_message_type");
        clientSocket->flush();
    }
}

void ClientConnection::handleSqlQuery(const QString &query) {
    m_server->addQueryToQueue(query, clientSocket);
}

void ClientConnection::handleImageUpload(const QByteArray &messageData) {
    // 解析图片上传数据 (二进制格式)
    QDataStream stream(messageData);
    stream.setByteOrder(QDataStream::LittleEndian);
    
    quint32 patientId, doctorId;
    QString direction, fileName;
    QByteArray imageData;
    
    stream >> patientId >> doctorId >> direction >> fileName >> imageData;
    
    DatabaseAccess dbAccess;
    QString savedFileName = dbAccess.saveImageMessage(patientId, doctorId, direction, imageData, fileName);
    
    if (!savedFileName.isEmpty()) {
        clientSocket->write("success:" + savedFileName.toUtf8());
    } else {
        clientSocket->write("failed");
    }
    clientSocket->flush();
}

void ClientConnection::handleImageDownload(const QString &fileName) {
    QString filePath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/images/" + fileName;
    
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        qDebug() << "Image file not found:" << filePath;
        clientSocket->write("file_not_found");
        clientSocket->flush();
        return;
    }
    
    QByteArray fileData = file.readAll();
    file.close();
    
    qDebug() << "Sending image file:" << fileName << "Size:" << fileData.size();
    
    // 发送文件数据
    QByteArray response;
    QDataStream stream(&response, QIODevice::WriteOnly);
    stream.setByteOrder(QDataStream::LittleEndian);
    
    stream << static_cast<quint32>(fileData.size());
    response.append(fileData);
    
    clientSocket->write(response);
    clientSocket->flush();
}

void ClientConnection::slotDisconnected() {
    qDebug() << "Client disconnected";
    emit disconnected();
}

Server::Server(quint16 port, QObject *parent)
    : QObject(parent), tcpServer(new QTcpServer(this)), dbAccess(new DatabaseAccess(this)), mutex(new QMutex) {
    if (!tcpServer->listen(QHostAddress::Any, port)) {
        qDebug() << "Server could not start!" << tcpServer->errorString();
        return;
    }
    connect(tcpServer, &QTcpServer::newConnection, this, &Server::onNewConnection);
    qDebug() << "Server is listening on port" << port;
}

void Server::onNewConnection() {
    while (tcpServer->hasPendingConnections()) {
        QTcpSocket *socket = tcpServer->nextPendingConnection();
        qDebug() << "New client connected from:" << socket->peerAddress().toString();
        ClientConnection *client = new ClientConnection(socket, this, this);
        connect(client, &ClientConnection::disconnected, client, &ClientConnection::deleteLater);
    }
}

void Server::processQueries() {
    mutex->lock();
    while (!queryQueue.isEmpty()) {
        auto queryData = queryQueue.dequeue();
        QString queryStr = queryData.first;
        QTcpSocket *clientSocket = queryData.second;

        qDebug() << "Processing query:" << queryStr;

        QSqlQuery query = dbAccess->runQuery(queryStr);

        if (query.isActive()) {
            bool hasResults = false;
            while (query.next()) {
                hasResults = true;
                QSqlRecord record = query.record();
                QStringList columns;
                for (int i = 0; i < record.count(); ++i) {
                    columns.append(record.value(i).toString());
                }
                QString result = columns.join("|").append("\n");
                clientSocket->write(result.toUtf8());
            }
            if (!hasResults) {
                clientSocket->write("failed");
            }
            clientSocket->flush();
        } else {
            clientSocket->write("Query failed");
            clientSocket->flush();
        }
    }
    mutex->unlock();
}

void Server::addQueryToQueue(const QString &query, QTcpSocket *clientSocket) {
    mutex->lock();
    queryQueue.enqueue(qMakePair(query, clientSocket));
    mutex->unlock();
    QTimer::singleShot(0, this, &Server::processQueries);
}
